import java.io.File

/**
 * 类与对象
 */
//没有类体可省略花括号
class Empty

//主构造函数(初始化代码放到init方法)可跟在类名后并可省略constructor关键字
//class Person constructor(name: String) {}
//如构造函数有注解或可见性修饰符需要有constructor关键字且在注解和修饰符后
//class Person public @Inject constructor(name: String) {}
//私有构造函数
//class Person private constructor(name: String) {}
class Person(name: String) {
    //主构造函数的初始化代码且可访问属性
    init {
        val lowercaseName = name.toLowerCase()
    }

    //次要构造函数通过this委托给主构造函数
    constructor(name: String, age: Int) : this(name) {
    }
}

//次要构造函数
class Customer {
    //次要构造函数
    private constructor(name: String) {}
}

//class默认是final不能被继承，使用open开放其可继承性
open class Shape {
    open val color: Int = 0

    open fun draw() {}
}

class Rectangle : Shape() {
    //覆盖属性
    override val color = 1

    //覆盖方法
    override fun draw() {
        super.draw()
    }
}

//属性覆盖可简写
//class Circle(override val color: Int = 5) : Shape() {}

//同事继承和实现的方法覆盖规则
open class A {
    open fun run() {}
}

interface B {
    fun run() {}
}

abstract class C : A() {
    //用抽象成员覆盖非抽象成员(open is redundant)
    /*open*/ abstract override fun run()
    fun sleep() {}
}

class D : A(), B {
    override fun run() {
        super<A>.run()
        super<B>.run()
    }

    //getter&setter可自定义逻辑
    var strPresentation: String
        get() {
            return this.toString()
        }
        set(value) {
            strPresentation = value
        }

    //field即幕后字段可以在访问器中引用
    var strField: String = ""
        set(value) {
            if (value.isEmpty()) field = value
        }

    //延迟初始化(必须var、只能用于不可null对象、不能是如Int等的原生类型)
    /*lateinit var anyLate: Any

    @SetUp
    fun setup() {
        anyLate = Any()
    }

    @Test
    fun test() {
        println("anyLate:$anyLate")
    }

    fun testLateInit() {
        println("testLateInit():${anyLate.hashCode()}")
    }*/
}

//接口覆盖冲突
interface IA {
    fun eat() = println("IA eat()")
    fun run()
}

interface IB {
    fun eat() = println("IB eat()")
    fun run() = println("IB run()")
}

class IC : IA {
    override fun eat() {
        super.eat()
        println("IC eat()")
    }

    override fun run() {
        println("IC run()")
    }
}

class ID : IA, IB {
    override fun eat() {
        super<IA>.eat()
        super<IB>.eat()
        println("ID eat()")
    }

    override fun run() {
        super<IB>.run()
        super.run()
    }
}

class TestIConflict {
    fun test() {
        val ic = IC()
        ic.eat()
        ic.run()
        val id = ID()
        id.eat()
        id.run()
    }
}

//sam单一抽象方法的接口用fun interface做前缀(使用lambda)
fun interface SamI {
    fun equal(i: Int, j: Int): Boolean
}

class TestSamI {
    //常规写法
    private val samINoLambda = object : SamI {
        override fun equal(i: Int, j: Int): Boolean {
            return i == j
        }
    }

    //lambda简化写法
    private val samIInLambda = SamI { i, j -> i == j }

    fun test() {
        println(samINoLambda.equal(1, 2))
        println(samIInLambda.equal(1, 1))
    }
}

//可见性修饰符
//private类内部
//protected类内部+子类
//internal能见到类声明的本模块内的任何客户端
//public能见到类声明的任何客户端

//扩展函数(建议单独写到一个类文件中做统一管理[给String扩展个xx()函数|可扩展不同参数列表的重载函数]|扩展是静态解析的)
fun String.xx(str: String) {
    println("String.xx:${str}")
}

//数据类
//如需生成一个无参的构造函数，则所有属性必须赋初始值
data class UserBean(val name: String = "", val age: Int = 0) {
    val address: String = ""//toString()中不会有address
}

//密封类sealed

//泛型
class Box<T>(private val t: T) {
    fun show() {
        println("show(), t:$t, type(String?):${t is String}")
    }
}

//内部类、匿名内部类object:className()
fun innerClass() {
    //匿名内部类可用lambda简写
    Thread(object : Runnable {
        override fun run() {
            TODO("Not yet implemented")
        }
    })

    Thread {
        TODO("Not yet implemented")
    }
}

//枚举类
enum class Color {
    RED, BLACK
}

enum class ColorInt(val rgb: Int, val colorName: String) {
    RED(0x110000, "red"), BLACK(0x000000, "black")
}

fun testEnum() {
    println("c:${Color.BLACK}")
    val ci = ColorInt.RED
    println("ci:${ci.name}, ${ci.rgb}, ${ci.colorName}")
}

//对象表达式object{...}-仅需要一个对象的时候
fun testJustNeedObject() {
    val init = 7

    val pair = object {
        var first = 1

        //对象表达式中可访问包含它的作用域的变量
        var second = 2 + init
    }
    println("pair:${pair.first}, ${pair.second}")
}

//单例
object SingleInstance {
    fun show() {
        println("SingleInstance.hashCode:${hashCode()}")
    }
}

fun testSingleInstance() {
    SingleInstance.show()
    SingleInstance.show()
}

//类型别名[-]-可为类型、函数起别名、内部类等
typealias AA<K> = MutableMap<K, MutableList<File>>
typealias BB = (Int, String) -> Unit

//内联类inline class className[-]

//委托[*]

//默认参数
fun defaultParam(x: Int = 0, y: Int = 1, z: () -> Unit) {
    println("defaultParam():$x, $y")
    //函数类型实例调用f.invoke(x)或者f(x)
    z.invoke()
    z()
}

fun testDefaultParam() {
    defaultParam(1) {}
    defaultParam(1, 2) {}
    defaultParam(z = { println("z") })
    defaultParam { println("z") }
}

//可变参数vararg
fun varargs(vararg nums: Int) {
    for (num in nums) {
        println("num:$num")
    }
}

//局部函数(局部函数可访问外部函数的变量)
fun partFunFather() {
    var index = 10
    fun partFunSon(i: Int = 2): Unit {
        println("index:$index")
        index += i
    }
    println("i:$index")
    partFunSon(16)
    println("i:$index")
}

//lambda
fun testLambda() {
    //_代替未使用的参数
    mapOf(("k1" to "v1"), ("k2" to "v2")).forEach { (_, v) ->
        println("v:$v")
    }

    //匿名函数
    val f = fun(x: Int, y: Int) = println("x:$x, y:$y")
    println(f(1, 3))
}

//@JvmOverloads生成多个重载
open class OA(a: Int, b: String, c: Float)
class OB @JvmOverloads constructor(a: Int, b: String = "", c: Float = 4.0f) : OA(a, b, c)

fun main() {

    val ob1 = OB(1)
    val ob2 = OB(1, "")
    val ob3 = OB(1, "", 1.0f)

//testLambda()

    //partFunFather()

    //varargs(1, 2, 3)

    //testDefaultParam()

    //testSingleInstance()

    //testJustNeedObject()

    //testEnum()

    //Box("hello world").show()

    //println(UserBean().toString())

    //String().xx("hello world")

    //D.TestSamI().test()

    //D.TestIConflict().test()


}


class Class {

}

